/*
 *
 * Copyright 2015 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package main

import (
	"log"
	"net"
	"os"
	"os/signal"
	"syscall"

	"gitee.com/microsevice/helloworld/cmd"
	"gitee.com/microsevice/helloworld/server"
	"gitee.com/microsevice/helloworld/server/grpc"
	"github.com/spf13/viper"
)

var (
	grpcServer grpc.Server  = nil
	listener   net.Listener = nil
)

// Signal handler
// graceful stop or reload
func SignalHandler() {

	sigCh := make(chan os.Signal, 1)
	// notify signal
	signal.Notify(sigCh, syscall.SIGTSTP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGUSR2)

	for {
		sig := <-sigCh

		switch sig {
		case syscall.SIGINT, syscall.SIGTERM, syscall.SIGTSTP, syscall.SIGQUIT:
			// stop
			signal.Stop(sigCh)
			grpcServer.GracefulStop()

			return
		case syscall.SIGUSR2:
			// reload
			err := server.GracefulRestart(listener, "--graceful")
			if err != nil {
				log.Printf("graceful restart error: %v", err)
			}
			grpcServer.GracefulStop()

			return
		}
	}
}

func main() {
	// program command
	cmd.Execute("server")

	// new grpc server
	grpcServer = grpc.NewServer()
	// register server implement
	grpcServer.Register(server.RegisterHelloServer)

	// get the run flag
	addr := viper.GetString("bind")
	graceful := viper.GetBool("graceful")

	log.Println("grpc server run", addr, graceful)

	var err error

	// graceful reload
	if graceful {
		// listening to existing file descriptor 3.
		file := os.NewFile(3, "")
		listener, err = net.FileListener(file)
	} else {
		// listening on a new file descriptor.
		listener, err = net.Listen("tcp", addr)
	}

	// listening error
	if err != nil {
		log.Fatalf("listener error: %v", err)
	}

	// go routine run server
	go func() {
		if err := grpcServer.Serve(listener); err != nil {
			log.Fatalln(err)
		}
	}()

	// signal handler
	SignalHandler()
}
